using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Common.Logging;

using IBatisNet.Common.Pagination;
using IBatisNet.DataMapper;
using IBatisNet.DataMapper.Configuration;

namespace EVegetable.Persistence.Mapper
{
    using EVegetable.Persistence;
    using EVegetable.Persistence.QueryModel;

    public class MyBatisDataContext : IDataContext, IDisposable
    {
        #region Fields

        private static SqlMapper _sqlMapper = null;
        private static ILog _log = LogManager.GetLogger(typeof(MyBatisDataContext));
        private static string _StatementName = string.Empty;
        
        #endregion

        #region Constructor
        
        /// <summary>
        /// Constructor of the MyBatisDataContext
        /// </summary>
        public MyBatisDataContext()
        {
            DomSqlMapBuilder builder = new DomSqlMapBuilder();
            _sqlMapper = builder.Configure() as SqlMapper;
        }
        #endregion

        #region IDataContext Members

        public bool IsDirty
        {
            get { throw new NotImplementedException(); }
        }

        public bool IsInTransaction
        {
            get { throw new NotImplementedException(); }
        }

        public string StatementName
        {
            get
            {
                lock (_StatementName)
                {
                    return _StatementName;
                }
            }
            set
            {
                lock (_StatementName)
                {
                    _StatementName = value;
                }
            }
        }

        public IList<T> GetAll<T>() where T : class, new()
        {
            IList<T> result = null;
            string className = typeof(T).Name;
            string statementName = string.Format("{0}.SelectAll{0}", className);

            try
            {
                if (!string.IsNullOrEmpty(this.StatementName)) statementName = string.Format("{0}.{1}", className, this.StatementName);

                result = _sqlMapper.QueryForList<T>(statementName, null);
            }
            catch (Exception ex)
            {
                _log.Error("Execute GetAll failure: " + ex.Message);
#if DEBUG

                throw ex;
#endif
            }

            this.StatementName = string.Empty;

            return result;
        }

        public IList<T> GetAll<T>(int pageIndex, int pageSize) where T : class, new()
        {
            IList<T> result = null;
            string className = typeof(T).Name;
            string statementName = string.Format("{0}.SelectAll{0}", className);

            try
            {
                if (!string.IsNullOrEmpty(this.StatementName)) statementName = string.Format("{0}.{1}", className, this.StatementName);

                result = _sqlMapper.QueryForList<T>(statementName, null, 0, 0);
            }
            catch (Exception ex)
            {
                _log.Error("Execute GetAll(Paged) failure: " + ex.Message);
#if DEBUG

                throw ex;
#endif
            }

            this.StatementName = string.Empty;

            return result;
        }

        public IList<T> GetByCriteria<T>(Query query) where T : class, new()
        {
            throw new NotImplementedException();
        }

        public IList<T> GetByCriteria<T>(Query query, int pageIndex, int pageSize) where T : class, new()
        {
            throw new NotImplementedException();
        }

        public T GetById<T>(object id) where T : class, new()
        {
            T result = null;
            string className = typeof(T).Name;
            string statementName = string.Format("{0}.Select{0}ByKey", className);

            try
            {
                if (!string.IsNullOrEmpty(this.StatementName)) statementName = string.Format("{0}.{1}", className, this.StatementName);

                result = _sqlMapper.QueryForObject<T>(statementName, id);
            }
            catch (Exception ex)
            {
                _log.Error("Execute GetById failure: " + ex.Message);
#if DEBUG

                throw ex;
#endif
            }

            this.StatementName = string.Empty;

            return result;
        }

        public int GetCount<T>()
        {
            throw new NotImplementedException();
        }

        public int GetCount<T>(Query query)
        {
            throw new NotImplementedException();
        }

        public void Add(object item)
        {
            if (item == null)
            {
                throw new ArgumentNullException();
            }

            string className = item.GetType().Name;
            string statementName = string.Format("{0}.Insert{0}", className);

            try
            {
                _sqlMapper.Insert(statementName, item);
            }
            catch (Exception ex)
            {
                _log.Error("Execute Add failure: " + ex.Message);
#if DEBUG

                throw ex;
#endif
            }
        }

        public void Delete(object item)
        {
            if (item == null)
            {
                throw new ArgumentNullException();
            }

            string className = item.GetType().Name;
            string statementName = string.Format("{0}.Delete{0}", className);

            try
            {
                _sqlMapper.Delete(statementName, item);
            }
            catch (Exception ex)
            {
                _log.Error("Execute Delete failure: " + ex.Message);
#if DEBUG

                throw ex;
#endif
            }
        }

        public void Save(object item)
        {
            if (item == null)
            {
                throw new ArgumentNullException();
            }

            string className = item.GetType().Name;
            string statementName = string.Format("{0}.Update{0}", className);

            try
            {
                _sqlMapper.Update(statementName, item);
            }
            catch (Exception ex)
            {
                _log.Error("Execute Save(Update) failure: " + ex.Message);
#if DEBUG

                throw ex;
#endif
            }
        }

        public void BeginTransaction()
        {
            _sqlMapper.BeginTransaction();
        }

        public void Commit()
        {
            _sqlMapper.CommitTransaction();
        }

        public void Rollback()
        {
            _sqlMapper.RollBackTransaction();
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            try
            {
                _sqlMapper.FlushCaches();
            }
            finally
            {
            }
        }

        #endregion
    }
}
